#include "Block_Manager.h"
#include "define.h"
#include "ex_util.h"

CBlock_Manager::CBlock_Manager()
	:m_bMovedBlock(false)
{
}

CBlock_Manager::~CBlock_Manager()
{
}


bool CBlock_Manager::init()
{
	bool bRet = false;

	do 
	{
		/*
		parent init call
		*/

		CCLayer::init();

		CreateBolck();

		// success
		bRet = true;
	} while(0);

	return bRet;
}

int CBlock_Manager::GenerateValidType()
{
	int nColor = 0;

	while(1)
	{
		float fRand = EX_UTIL::GetRand();
		nColor = (int)fRand%E_BLOCK_MAX;

		if( m_nBlockTypeCount[nColor] < (BLOCK_TOTAL_COUNT/E_BLOCK_MAX)+1 )
		{
			m_nBlockTypeCount[nColor]++;
			break;
		}
	}

	return nColor;
}

void CBlock_Manager::CreateBolck()
{
	memset(&m_nBlockTypeCount, 0, sizeof(int)*E_BLOCK_MAX);

	//m_vBlocks
	for( int j=0; j<GRID_HEIGHT; j++ )
	{
		for( int i=0; i<GRID_WITH; i++ )
		{
			int nType = GenerateValidType();
			CBlock* pBlock = CBlock::blockWithType( nType );
			//pBlock->setAnchorPoint(ccp(0.5f,0.5f));
			pBlock->setAnchorPoint(CCPointZero);
			pBlock->setPosition( ccp( 48+(i*56) , 96+(j*56) ) );
			addChild(pBlock,((j*GRID_HEIGHT)+i));
			m_vBlocks.push_back( pBlock );
		}
	}
}

void CBlock_Manager::onEnter()
{
    CCTouchDispatcher::sharedDispatcher()->addTargetedDelegate(this, 0, true);
	//CCTouchDispatcher::sharedDispatcher()->addStandardDelegate(this,0);
	CCLayer::onEnter();
}

void CBlock_Manager::onExit()
{
	//CCTouchDispatcher::sharedDispatcher()->removeDelegate(this);
	CCTouchDispatcher::sharedDispatcher()->removeDelegate(this);
	CCLayer::onExit();
}

//bool CBlock_Manager::containsTouchLocation(CCTouch* touch)
//{
//	CCRect block_rect;
//	block_rect.size = m_pImage->getContentSize();
//	block_rect.origin = ccp( m_pImage->getPosition().x - (m_pImage->getContentSize().width/2),  m_pImage->getPosition().y - (m_pImage->getContentSize().height/2));
//
//	return CCRect::CCRectContainsPoint(block_rect, convertTouchToNodeSpaceAR(touch));
//}
//
bool CBlock_Manager::ccTouchBegan(CCTouch* touch, CCEvent* event)
{
	  //CCPoint touchPoint = touch->locationInView( touch->view() );
	  //touchPoint = CCDirector::sharedDirector()->convertToGL( touchPoint );
	  CCPoint touchPoint = this->convertTouchToNodeSpaceAR(touch);
	  int nIdx = FindBlock(touchPoint);
			  
	  if( nIdx == -1 )
	  	return false;

	  if(m_vBlocks[nIdx]->isDoing())
		  return false;
	
	  m_toucheBeginPt = touchPoint;

	  m_vSelectedBlock.insert(std::pair<int,int>(touch->id(),nIdx));
	  reorderChild( m_vBlocks[nIdx], 100 );

	  return true;
}

void CBlock_Manager::ccTouchMoved(CCTouch* touch, CCEvent* event)
{
	std::map<int,int>::iterator nItr = m_vSelectedBlock.find(touch->id());
	if(nItr!=m_vSelectedBlock.end())
	{

		/*CCPoint touchPoint = touch->locationInView( touch->view() );
		touchPoint = CCDirector::sharedDirector()->convertToGL( touchPoint );*/
		CCPoint touchPoint = this->convertTouchToNodeSpaceAR(touch);

		CCPoint pre_touchPoint = touch->previousLocationInView( touch->view() );
		pre_touchPoint = CCDirector::sharedDirector()->convertToGL( pre_touchPoint );
		
		CCPoint diff = ccpSub(pre_touchPoint,touchPoint);

		CCPoint pos = m_vBlocks[nItr->second]->getPosition();
		pos = ccpSub(pos,diff);

		m_vBlocks[nItr->second]->setPosition(pos);

	}
	m_bMovedBlock = true;
}

void CBlock_Manager::ccTouchEnded(CCTouch* touch, CCEvent* event)
{
	std::map<int,int>::iterator nItr = m_vSelectedBlock.find(touch->id());
	if(nItr!=m_vSelectedBlock.end())
	{
		if(m_bMovedBlock)
		{
			/*CCPoint touchPoint = touch->locationInView( touch->view() );
			touchPoint = CCDirector::sharedDirector()->convertToGL( touchPoint );*/
			CCPoint touchPoint = this->convertTouchToNodeSpaceAR(touch);

			CCPoint retPt;

			bool bRet = CalibrationPosition(touchPoint,retPt);

			if(bRet)
			{
				int nDestIndex = FindBlock(retPt);
				if( nDestIndex == nItr->second)
				{
					bRet = false;
				}
				else
				{
					CCPoint OriginalPos;
					GetGridPostion(nItr->second,OriginalPos);

					m_vBlocks[nItr->second]->BlockFlyTo(retPt);
					m_vBlocks[nDestIndex]->BlockFlyTo(OriginalPos);

					std::swap(m_vBlocks[nItr->second],m_vBlocks[nDestIndex]);
				}
			}

			if(!bRet)
			{
				GetGridPostion(nItr->second,retPt);
				m_vBlocks[nItr->second]->setPosition(retPt);
			}
		}
		else
		{
			m_vBlocks[nItr->second]->BlockRotate();
		}

		m_vSelectedBlock.erase(nItr);
	}

	m_bMovedBlock = false;
}

void CBlock_Manager::ccTouchCancelled(CCTouch *touch, CCEvent *pEvent)
{
	std::map<int,int>::iterator nItr = m_vSelectedBlock.find(touch->id());
	if(nItr!=m_vSelectedBlock.end())
	{
		m_vSelectedBlock.erase(nItr);
	}
}

//void CBlock_Manager::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent)
//{
//	 CCSetIterator it = pTouches->begin();
//	 int nTouchZorder = 100;
//	 for(; it!=pTouches->end(); it++)
//	 {
//		  CCTouch* touch = (CCTouch*)(*it);
//
//		  CCPoint touchPoint = touch->locationInView( touch->view() );
//		  touchPoint = CCDirector::sharedDirector()->convertToGL( touchPoint );
//		  
//		  int nIdx = FindBlock(touchPoint);
//				  
//		  if( nIdx == -1 )
//		  	continue;
//
//		  m_vSelectedBlock.insert(std::pair<int,int>(touch->id(),nIdx));
//		  reorderChild( m_vBlocks[nIdx], nTouchZorder );
//		  nTouchZorder++;
//	 }
//}
//
//void CBlock_Manager::ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent)
//{
//	CCSetIterator it = pTouches->begin();
//	for(; it!=pTouches->end(); it++)
//	{
//		CCTouch* touch = (CCTouch*)(*it);
//
//		std::map<int,int>::iterator nItr = m_vSelectedBlock.find(touch->id());
//		if(nItr!=m_vSelectedBlock.end())
//		{
//
//			CCPoint touchPoint = touch->locationInView( touch->view() );
//			touchPoint = CCDirector::sharedDirector()->convertToGL( touchPoint );
//
//			CCPoint pre_touchPoint = touch->previousLocationInView( touch->view() );
//			pre_touchPoint = CCDirector::sharedDirector()->convertToGL( pre_touchPoint );
//
//			CCPoint diff = ccpSub(pre_touchPoint,touchPoint);
//
//			CCPoint pos = m_vBlocks[nItr->second]->getPosition();
//			pos = ccpSub(pos,diff);
//
//			m_vBlocks[nItr->second]->setPosition(pos);
//		}
//	}
//}
//
//void CBlock_Manager::ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent)
//{
//	CCSetIterator it = pTouches->begin();
//	for(; it!=pTouches->end(); it++)
//	{
//		CCTouch* touch = (CCTouch*)(*it);
//
//		std::map<int,int>::iterator nItr = m_vSelectedBlock.find(touch->id());
//		if(nItr!=m_vSelectedBlock.end())
//		{
//			CCPoint touchPoint = touch->locationInView( touch->view() );
//			touchPoint = CCDirector::sharedDirector()->convertToGL( touchPoint );
//
//			CCPoint retPt;
//			if(CalibrationPosition(touchPoint,retPt))
//			{
//				int nDestIndex = FindBlock(retPt);
//
//				CCPoint OriginalPos;
//				GetGridPostion(nItr->second,OriginalPos);
//
//				m_vBlocks[nItr->second]->setPosition(retPt);
//				m_vBlocks[nDestIndex]->setPosition(OriginalPos);
//
//				std::swap(m_vBlocks[nItr->second],m_vBlocks[nDestIndex]);
//			}
//			else
//			{
//				GetGridPostion(nItr->second,retPt);
//				m_vBlocks[nItr->second]->setPosition(retPt);
//			}
//			m_vSelectedBlock.erase(nItr);
//		}
//	}
//}
//
//ccTouchesCancelled(CCSet *pTouches, CCEvent *pEvent)
//{
//	CCSetIterator it = pTouches->begin();
//	for(; it!=pTouches->end(); it++)
//	{
//		CCTouch* touch = (CCTouch*)(*it);
//
//		std::map<int,int>::iterator nItr = m_vSelectedBlock.find(touch->id());
//		if(nItr!=m_vSelectedBlock.end())
//		{
//			m_vSelectedBlock.erase(nItr);
//		}
//	}
//}

int CBlock_Manager::FindBlock(CCPoint pt)
{
	if( pt.y < 68 || pt.y > 460 || pt.x < 20 || pt.x > 300 )
	{
		return -1;
	}

	int x_pos = pt.x - 20;
	int y_pos = pt.y - 68;

	x_pos = x_pos/56;
	y_pos = y_pos/56;

	int nIndex = (y_pos*5)+x_pos;

	return nIndex;
}

bool CBlock_Manager::GetGridPostion(int nIdx, CCPoint& retPt )
{
	if( BLOCK_TOTAL_COUNT <= nIdx )
		return false;

	int nx = nIdx%5;
	int ny = nIdx/5;

	retPt.x = (nx*56)+48;
	retPt.y = (ny*56)+96;

	return true;
}

bool CBlock_Manager::CalibrationPosition(CCPoint pt, CCPoint& retPt)
{
	int nIdx = FindBlock(pt);

	if( nIdx < 0 )
		return false;

	return GetGridPostion(nIdx,retPt);
}